#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <sys/time.h>
 
#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "basefunc.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "memdb.h"
#include "message.h"
#include "ex_module.h"
#include "sys_func.h"
#include "integrity_measure.h"
#include "system_entity.h"
#include "integrity_verify.h"
// add para lib_include
BYTE buffer[1024];
int compare_measure_result(RECORD(INTEGRITY_COLLECT,UNITSET_MEASURE) * measure_value,
		RECORD(MESSAGE,MODULE_STATE) * module_state);
int integrity_verify_init(void * sub_proc, void * para)
{
	int ret;
	// add yorself's module init func here
	return 0;
}
int integrity_verify_start(void * sub_proc, void * para)
{
	int ret;
	void * recv_msg;
	int type;
	int subtype;
	// add yorself's module exec func here
	usleep(1000*50);
	ret=proc_integrity_verify(sub_proc,NULL);	

	while(1)
	{
		usleep(time_val.tv_usec);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
		if((type==TYPE(INTEGRITY_COLLECT)) && (subtype==SUBTYPE(INTEGRITY_COLLECT,UNITSET_MEASURE)))
		{
			ret=proc_integrity_verify(sub_proc,recv_msg);
		}
		else
		{
			ret=proc_integrity_verify_inexpand(sub_proc,recv_msg);
		}	
	
	}
	return 0;
}

int proc_integrity_verify(void * sub_proc,void * recv_msg)
{
	int ret=0;
	int count=0;
	RECORD(INTEGRITY_COLLECT,UNITSET_MEASURE) * measure_value;
	RECORD(MESSAGE,MODULE_STATE) * compare_result;
	DB_RECORD * db_record;
	void * send_msg;
	int i=0;

	ret=message_get_record(recv_msg,&measure_value,0);
	if(ret<0)
		return -EINVAL;
	if(measure_value == NULL)
		return -EINVAL;
	compare_result=Talloc0(sizeof(*compare_result));
	if(compare_result==NULL)
		return -ENOMEM;
	
	ret=compare_measure_result(measure_value,compare_result);
	if(ret<0)
		return ret;
	
	send_msg=recv_msg;
	message_set_flag(send_msg,message_get_flag(send_msg)&MSG_FLAG_FOLLOW);
	message_add_expand_data(send_msg,TYPE_PAIR(MESSAGE,MODULE_STATE),compare_result);

	ex_module_sendmsg(sub_proc,send_msg);

	return 0;
}

int proc_integrity_verify_inexpand(void * sub_proc,void * recv_msg)
{
	int ret=0;
	int count=0;
	RECORD(INTEGRITY_COLLECT,UNITSET_MEASURE) * measure_value;
	RECORD(MESSAGE,MODULE_STATE) * compare_result;
	DB_RECORD * db_record;
	MSG_EXPAND * msg_expand;
	void * send_msg;
	int i=0;

	ret=message_remove_expand(recv_msg,TYPE_PAIR(INTEGRITY_COLLECT,UNITSET_MEASURE),&msg_expand);
	if(ret<0)
		return -EINVAL;
	if(msg_expand==NULL)
		return -EINVAL;
	measure_value =msg_expand->expand;

	compare_result=Talloc0(sizeof(*compare_result));
	if(compare_result==NULL)
		return -ENOMEM;

	ret=compare_measure_result(measure_value,compare_result);
	if(ret<0)
		return ret;
	
	send_msg=recv_msg;
	message_set_flag(send_msg,message_get_flag(send_msg)&MSG_FLAG_FOLLOW);
	message_add_expand_data(send_msg,TYPE_PAIR(MESSAGE,MODULE_STATE),compare_result);

	ex_module_sendmsg(sub_proc,send_msg);

	return 0;
}

int compare_measure_result(RECORD(INTEGRITY_COLLECT,UNITSET_MEASURE) * measure_value,
		RECORD(MESSAGE,MODULE_STATE) * module_state)
{
	int ret;
	int i,count;
	int pathlen;
	DB_RECORD * db_record;
	
	RECORD(INTEGRITY_COLLECT,UNITSET_MEASURE) * compare_value;
	RECORD(SYSTEM_ENTITY,UNIT_SET) * unitset;

	Memset(module_state->name,0,DIGEST_SIZE);
	db_record=memdb_find_first(TYPE_PAIR(INTEGRITY_COLLECT,UNITSET_MEASURE),"uuid",measure_value->uuid);
	if(db_record==NULL)
	{
		module_state->state=0;
		return 0;
	}
	module_state->state=1;

	db_record=memdb_find_first(TYPE_PAIR(SYSTEM_ENTITY,UNIT_SET),"uuid",measure_value->unitset_uuid);
	if(db_record!=NULL)
	{
		unitset=db_record->record;
		Strncpy(module_state->name,unitset->name,DIGEST_SIZE);
	}

	return 1;		
}
